<?php
/*
 * 文件上传的类   所有文件上传都可以通过本类进行
 * 在控制器controller或者model使用大U方法就可以实例化上传文件类的对象  进行上传文件的使用
 * 必须$_FILES中有信息才可以使用本类
 * 支持多文件上传
 * */
header("Content-type: text/html; charset=utf-8");
class upload{
    private $maxSize;               //文件上传文件大小的上限限制     默认2M
    private $exts;                  //允许上传文件的格式(以后缀为基准) 默认空(没有限制,不推荐)
    private $savePath;              //文件上传后保存的目录(以根目录__ROOT__为基础)   默认是根目录下的uploads文件夹
    private $is_http_post;          //是否必须通过http post过来的才上传     默认是true
    private $is_uniqid;             //是否使用唯一名称保存文件.默认false
    private $is_date;               //是否以日期作为再一级的子目录  默认是false的
    private $is_true_img;           //上传的文件是否是真实的图片  默认是false  如果不是图片上传就不要设置未true
    /*
     * 构造函数
     * 初始化默认的数据  用户可以在构造函数中进行其他参数修改
     *                 用户也可以通过调用相应的方法进行参数的修改
     * */
    public function __construct($maxSize=2097152,$exts=array(),$savePath="uploads",$is_http_post=true,$is_uniqid=false,$is_date=true,$is_true_img=false){
        $this->maxSize = $maxSize;
        $this->exts = $exts;
        $this->savePath = __ROOT__."/".$savePath;
        $this->is_http_post = $is_http_post;
        $this->is_uniqid = $is_uniqid;
        $this->is_date = $is_date;
        $this->is_true_img = $is_true_img;
    }



    /*
     * 上传文件     支持多文件上传
     * 从$_FILES中获取信息然后经过校验后进行上传文件
     * 返回一个$result关联数组   error  错误码
     *                         message 错误信息  失败的原因  成功为保存的路径.相对于根目录的
     * */
    public function upload(){
        if(!file_exists($this->savePath)){              //判断上传路径的目录是否存在
            mkdir(iconv("UTF-8", "GBK", $this->savePath),0777,true);                     //没有就创建目录
        }
        $arr = $this->format();
        $arr_len = count($arr);             //获取上传文件的个数
        $return_arr = array();
        for($i = 0;$i < $arr_len;$i++){
            $return_arr[$i]["file_name"] = $arr[$i]["file_name"];
            if($arr[$i]["error"] == 0){
                if($arr[$i]["size"] > $this->maxSize){          //检测大小限制是否符合
                    $return_arr[$i]["error"] = 9;
                    $return_arr[$i]["message"] = "上传的文件大小大于程序限制的最大值";
                    continue;
                }
                $ext = explode(".",$arr[$i]["name"]);
                $ext = strtolower(end($ext));
                if(count($this->exts) > 0 && !in_array($ext,$this->exts)){              //检测文件类型
                    $return_arr[$i]["error"] = 10;
                    $return_arr[$i]["message"] = "非法文件上传类型";
                    continue;
                }
                if($this->is_http_post && !is_uploaded_file($arr[$i]["tmp_name"])){         //检测是否通过http post发送
                    $return_arr[$i]["error"] = 11;
                    $return_arr[$i]["message"] = "上传文件不是通过http post的方式传送过来";
                    continue;
                }
                if($this->is_true_img && !getimagesize($arr[$i]["tmp_name"])){
                    $return_arr[$i]["error"] = 12;
                    $return_arr[$i]["message"] = "上传的图片不是真实图片";
                    continue;
                }
                $name = "";            //组织保存的名称(或许有子目录)
                if($this->is_date){
                    $name .= date("Y-m-d",time())."/";
                    if(!file_exists($this->savePath."/".$name)){
                        mkdir($this->savePath."/".$name);
                    }
                }
                if($this->is_uniqid){               //是否需要产生唯一id名称
                    $name .= md5(uniqid(microtime(true),true)).".".$ext;
                }else{
                    $name .= $arr[$i]["name"];
                }
                unset($ext);
                $save_name=iconv("UTF-8","gb2312", $name);
                if(move_uploaded_file($arr[$i]["tmp_name"],$this->savePath."/".$save_name)){
                    $return_arr[$i]["error"] = 0;           //上传成功
                    $return_arr[$i]["message"] = str_replace(__ROOT__."/","",$this->savePath."/".$name);        //返回保存的路径.相对于根目录
                }else{
                    $return_arr[$i]["error"] = 13;           //上传失败
                    $return_arr[$i]["message"] = "转移文件失败导致上传失败";
                }
                unset($save_name,$name);
            }else{
                $return_arr[$i]["error"] = $arr[$i]["error"];
                switch($arr[$i]["error"]){
                    case 1:$return_arr[$i]["message"] = "上传的文件大小大于配置限制的文件大小";
                           break;
                    case 2:$return_arr[$i]["message"] = "上传文件大于了HTML表单中MAX_FILE_SIZE的值";
                           break;
                    case 3:$return_arr[$i]["message"] = "文件只有部分成功上传";
                           break;
                    case 4:$return_arr[$i]["message"] = "没有选择上传的文件";
                           break;
                    case 6:$return_arr[$i]["message"] = "找不到临时文件";
                           break;
                    case 7:$return_arr[$i]["message"] = "文件写入失败";
                           break;
                    case 8:$return_arr[$i]["message"] = "上传的文件被php扩展程序中断";
                           break;
                }
            }
        }
        unset($arr,$arr_len);
        return $return_arr;
    }

    /*
     * 对$_FILES数个进行格式化(支持各种形式的上传)
     * 参数是$_FILES      不用传入  自动获取(全局变量)
     * */
    private function format(){
        $arr = array();
        foreach($_FILES as $k => $v){
            if(is_array($v["name"])){
                $files_len = count($v["name"]);
                for($i = 0;$i < $files_len;$i++){
                    $temp["file_name"] = $k;
                    $temp["name"] = $v["name"][$i];
                    $temp["type"] = $v["type"][$i];
                    $temp["tmp_name"] = $v["tmp_name"][$i];
                    $temp["error"] = $v["error"][$i];
                    $temp["size"] = $v["size"][$i];
                    $arr[] = $temp;
                    unset($temp);
                }
            }else{
                $v["file_name"] = $k;
                $arr[] = $v;
            }
        }
        return $arr;
    }

    /*
     * 设置上传文件大小的限制maxSize  默认2M  以字节数计算
     * */
    public function setMaxSize($size=2097152){
        if(is_numeric($size)) {
            $this->maxSize = $size;
        }
    }

    /*
     * 设置格式的限制  默认是空 表示不限制
     * 参数必须是数组
     * */
    public function setExts($exts=array()){
        if(is_array($exts)){
            $this->exts = $exts;
        }else{
            die("<h3>传入的参数不是一个数组!</h3>");
        }
    }

    /*
     * 设置保存的路径  默认空  空表示在根目录下的uploads文件夹
     * 参数是字串  第一个不用带/
     * */
    public function setSavePath($savePath=""){
        $this->savePath = __ROOT__."/".$savePath;
    }

    /*
     * 设置数据过来的限制 是否必须通过http post方式传过来
     * 默认是true
     * */
    public function setHttpPost($is_http_post=true){
        if(is_bool($is_http_post)) {
            $this->is_http_post = $is_http_post;
        }
    }

    /*
     * 设置是否文件名称使用唯一id
     * 默认false 使用原来的名称  true 使用后台产生的唯一id(防止覆盖)
     * */
    public function setUniqid($is_uniqid=true){
        if(is_bool($is_uniqid)) {
            $this->is_uniqid = $is_uniqid;
        }
    }

    /*
     * 设置是否在文件前再加一层子目录  以日期为名称的文件夹 方便管理
     * 默认是false
     * */
    public function setIsDate($is_date=true){
        if(is_bool($is_date)) {
            $this->is_date = $is_date;
        }
    }

    /*
     * 设置上传的图片必须为真实图片
     * 默认是false
     * */
    public function setTrueImg($is_true_img=true){
        if(is_bool($is_true_img)) {
            $this->is_true_img = $is_true_img;
        }
    }
}